package com.suxin.ble.demo;

import android.Manifest;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.os.Handler;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.clj.fastble.utils.HexUtil;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = MainActivity.class.getSimpleName();
    private Context mContext;
    private static final int REQUEST_CODE_OPEN_GPS = 1;
    private static final int REQUEST_CODE_PERMISSION_LOCATION = 2;
    private String deviceName = "SuXin Iot";
    private ProgressDialog progressDialog;
    private TextView result;
    boolean isCONotifyOpen = false;
    boolean isAccNotifyOpen = false;
    private String status = "";
    private Button btnNotify;
    private TextView notify;
    private TextView tvAcc;
    private Button btnNotifyAcc;
    private TextView tvCOresult;
    private TextView tvAccResult;
    private TextView tvPress;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = MainActivity.this;
        BleManager.getInstance().init(getApplication());
        BleManager.getInstance()
                .enableLog(true)
                .setReConnectCount(1, 5000)
                .setConnectOverTime(20000)
                .setOperateTimeout(5000);
        checkPermissions();
        initView();

    }

    private void initView() {
        progressDialog = new ProgressDialog(MainActivity.this);


//        tvCOresult = findViewById(R.id.tv_co_result);
//        tvAccResult = findViewById(R.id.tv_acc_result);
//        tvPress = findViewById(R.id.tv_co_result);

        notify = findViewById(R.id.tv_notify);
        result = findViewById(R.id.tv_result);
        tvAcc = findViewById(R.id.tv_acc);
        findViewById(R.id.btn_scan).setOnClickListener(this);
        findViewById(R.id.btn_disconnect).setOnClickListener(this);
        findViewById(R.id.btn_write).setOnClickListener(this);
        btnNotifyAcc = findViewById(R.id.btn_notify_acc);
        btnNotifyAcc.setOnClickListener(this);
        btnNotify = findViewById(R.id.btn_notify);
        btnNotify.setTag("close");
        btnNotify.setOnClickListener(this);
    }

    private void startScan() {
        BleManager.getInstance().scan(new BleScanCallback() {
            @Override
            public void onScanStarted(boolean success) {
                Log.i(TAG, "onScanStarted: ");
                progressDialog.setMessage("正在扫描...");
                progressDialog.show();
            }

            @Override
            public void onLeScan(BleDevice bleDevice) {
                super.onLeScan(bleDevice);
            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                Log.i(TAG, "onScanning: " + "name:" + bleDevice.getDevice().getName() + "mac " + bleDevice.getDevice().getAddress());
                if (bleDevice.getDevice().getName().equals(deviceName)) {
                    progressDialog.setMessage("连接中...");
                    progressDialog.show();
                    BleManager.getInstance().cancelScan();
                    connnect(bleDevice);
                }
            }

            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                Log.i(TAG, "onScanFinished: " + scanResultList.size());
                if (scanResultList.size() == 0) {
                    showToast("未发现任何设备");
                    dismiss();
                } else {
                    for (int i = 0; i < scanResultList.size(); i++) {
                        if (!scanResultList.get(i).getName().equals(deviceName)) {
                            showToast("扫描结束,未找到设备");
                        }
                    }
                }
//                dismiss();
            }
        });
    }

    /*
     * 连接设备
     * */

    private void connnect(BleDevice bleDevice) {
        BleManager.getInstance().connect(bleDevice, new BleGattCallback() {
            @Override
            public void onStartConnect() {
                progressDialog.setMessage("连接设备...");
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                showToast("连接失败");
                dismiss();
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                result.setText("设备名称:" + bleDevice.getName() + "\n" + "mac:" + bleDevice.getMac());
                progressDialog.setMessage("连接成功");
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        dismiss();
                    }
                }, 1000);

            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {

            }
        });
    }

    private void dismiss() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }

    private void setScanRule() {
//        String[] uuids;
//        String str_uuid = et_uuid.getText().toString();
//        if (TextUtils.isEmpty(str_uuid)) {
//            uuids = null;
//        } else {
//            uuids = str_uuid.split(",");
//        }
//        UUID[] serviceUuids = null;
//
//        if (uuids != null && uuids.length > 0) {
//            serviceUuids = new UUID[uuids.length];
//            for (int i = 0; i < uuids.length; i++) {
//                String name = uuids[i];
//                String[] components = name.split("-");
//                if (components.length != 5) {
//                    serviceUuids[i] = null;
//                } else {
//                    serviceUuids[i] = UUID.fromString(uuids[i]);
//                }
//            }
//        }
//
//        String[] names;
//        String str_name = et_name.getText().toString();
//        if (TextUtils.isEmpty(str_name)) {
//            names = null;
//        } else {
//            names = str_name.split(",");
//        }
//
//        String mac = et_mac.getText().toString();
//
//        boolean isAutoConnect = sw_auto.isChecked();

        BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
//                .setServiceUuids(serviceUuids)      // 只扫描指定的服务的设备，可选
                .setDeviceName(true, "SuXin Iot")   // 只扫描指定广播名的设备，可选
//                .setDeviceMac(mac)                  // 只扫描指定mac的设备，可选
                .setAutoConnect(true)      // 连接时的autoConnect参数，可选，默认false
                .setScanTimeOut(10000)              // 扫描超时时间，可选，默认10秒
                .build();
        BleManager.getInstance().initScanRule(scanRuleConfig);
    }


    private void checkPermissions() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (!bluetoothAdapter.isEnabled()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, 0x02);
            return;
        }
        requestPermission();
    }

    private void requestPermission() {
        String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
        List<String> permissionDeniedList = new ArrayList<>();
        for (String permission : permissions) {
            int permissionCheck = ContextCompat.checkSelfPermission(this, permission);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                onPermissionGranted(permission);
            } else {
                permissionDeniedList.add(permission);
            }
        }
        if (!permissionDeniedList.isEmpty()) {
            String[] deniedPermissions = permissionDeniedList.toArray(new String[permissionDeniedList.size()]);
            ActivityCompat.requestPermissions(this, deniedPermissions, REQUEST_CODE_PERMISSION_LOCATION);
        }
    }

    @Override
    public final void onRequestPermissionsResult(int requestCode,
                                                 @NonNull String[] permissions,
                                                 @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_CODE_PERMISSION_LOCATION:
                if (grantResults.length > 0) {
                    for (int i = 0; i < grantResults.length; i++) {
                        if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                            onPermissionGranted(permissions[i]);
                        } else {
                            finish();
                        }
                    }
                }
                break;
        }
    }


    private void onPermissionGranted(String permission) {
        switch (permission) {
            case Manifest.permission.ACCESS_FINE_LOCATION:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !checkGPSIsOpen()) {
                    new AlertDialog.Builder(this)
                            .setTitle(R.string.notifyTitle)
                            .setMessage(R.string.gpsNotifyMsg)
                            .setNegativeButton(R.string.cancel,
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            finish();
                                        }
                                    })
                            .setPositiveButton(R.string.setting,
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                                            startActivityForResult(intent, REQUEST_CODE_OPEN_GPS);
                                        }
                                    })

                            .setCancelable(false)
                            .show();
                } else {
                    setScanRule();
                    startScan();
                }
                break;
        }
    }

    private boolean checkGPSIsOpen() {
        LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        if (locationManager == null)
            return false;
        return locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 0x02 && resultCode == RESULT_OK) {
            requestPermission();
        } else {
            finish();
        }

        if (requestCode == REQUEST_CODE_OPEN_GPS) {
            if (checkGPSIsOpen()) {
                setScanRule();
                startScan();
            }
        }

    }


    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume: ");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        BleManager.getInstance().disconnectAllDevice();
        BleManager.getInstance().destroy();
        Log.i(TAG, "onDestroy: ");
    }

    private void showToast(String msg) {
        Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public void onClick(View v) {

        int id = v.getId();
        switch (id) {
            case R.id.btn_notify_acc:
                BleDevice deviceAcc = Utils.getDevice(mContext);
                BluetoothGattService serviceAcc = Utils.getService(mContext, deviceAcc, 3);
                BluetoothGattCharacteristic charastersticAcc = Utils.getCharasterstic(serviceAcc, 2);

                if (serviceAcc==null || charastersticAcc==null){
                    showToast("暂无设备连接");
                    return;
                }
                if (!isAccNotifyOpen) {
                    btnNotifyAcc.setText("加速度通知（开）");
                    BleManager.getInstance().notify(deviceAcc,
                            charastersticAcc.getService().getUuid().toString(),
                            charastersticAcc.getUuid().toString(),
                            new BleNotifyCallback() {
                                @Override
                                public void onNotifySuccess() {
                                    Log.i(TAG, "onNotifySuccess: ");
                                }

                                @Override
                                public void onNotifyFailure(BleException exception) {
                                    Log.i(TAG, "onNotifyFailure: ");
                                }

                                @Override
                                public void onCharacteristicChanged(byte[] data) {
                                    Log.i(TAG, "onCharacteristicChanged: ");
                                    setOnCharacteristicChanged(tvAcc, data, "Acc");
                                }
                            });

                }else {

                    btnNotifyAcc.setText("加速度通知（关）");
                    BleManager.getInstance().stopNotify(
                            deviceAcc,
                            charastersticAcc.getService().getUuid().toString(),
                            charastersticAcc.getUuid().toString());
                    tvAcc.setText("加速度：");
                }

                isAccNotifyOpen = !isAccNotifyOpen;
                break;
            case R.id.btn_disconnect:
                BleManager.getInstance().disconnectAllDevice();
                result.setText("暂无设备连接");
                showToast("设备已断开");
                break;
            case R.id.btn_scan:

                if (BleManager.getInstance().getAllConnectedDevice().size() == 0) {
                    startScan();
                } else {
                    showToast("设备已连接");
                }
                break;
            case R.id.btn_write:
                BleDevice bleDevice = Utils.getDevice(mContext);
                BluetoothGattService service = Utils.getService(mContext, bleDevice, 4);
                BluetoothGattCharacteristic charasterstic = Utils.getCharasterstic(service, 4);
                if (charasterstic==null|| service ==null){
                    showToast("暂无设备连接");
                    return;
                }
//                BleDevice bleDevice = getDevice();
                if (bleDevice == null) return;
//                BluetoothGattService service = getService(bleDevice, 4);
//                BluetoothGattCharacteristic charasterstic = getCharasterstic(service, 4);
                BleManager.getInstance().write(
                        bleDevice,
                        charasterstic.getService().getUuid().toString(),
                        charasterstic.getUuid().toString(),
                        HexUtil.hexStringToBytes(getCurrentStatus()),
                        new BleWriteCallback() {

                            @Override
                            public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Log.i(TAG, "run: ");
                                        Button write = findViewById(R.id.btn_write);
                                        write.setText(status.equals("01") ? "写（柴油机开）" : "写（柴油机关）");
                                    }
                                });
                            }

                            @Override
                            public void onWriteFailure(final BleException exception) {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Log.i(TAG, "run: ");
                                        Button write = findViewById(R.id.btn_write);
                                        write.setText("写（失败）");
                                    }
                                });
                            }
                        });

                break;
            case R.id.btn_notify:
                if (btnNotify.getTag().equals("close")) {
                    btnNotify.setTag("open");
                    btnNotify.setText("notify(开)");

                    BleDevice device = Utils.getDevice(mContext);
                    BluetoothGattService notifyService = Utils.getService(mContext, device, 4);
                    final BluetoothGattCharacteristic bluetoothGattCharacteristic = Utils.getCharasterstic(notifyService, 2);
                    if (notifyService==null || bluetoothGattCharacteristic==null){
                        showToast("暂无设备连接");
                        return;
                    }
//                    BleDevice device = getDevice();
//                    BluetoothGattService notifyService = getService(device, 4);
//                    final BluetoothGattCharacteristic bluetoothGattCharacteristic = notifyService.getCharacteristics().get(2);

                    BleManager.getInstance().notify(
                            device,
                            bluetoothGattCharacteristic.getService().getUuid().toString(),
                            bluetoothGattCharacteristic.getUuid().toString(),
                            new BleNotifyCallback() {

                                @Override
                                public void onNotifySuccess() {
                                    showToast("通知成功");
                                }

                                @Override
                                public void onNotifyFailure(final BleException exception) {
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            showToast("通知失败" + exception.getDescription().toString());
                                            Log.i(TAG, "run: " + exception.getDescription().toString());
                                        }
                                    });
                                }

                                @Override
                                public void onCharacteristicChanged(final byte[] data) {
                                    runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            Log.i(TAG, "run: " + HexUtil.formatHexString(bluetoothGattCharacteristic.getValue(), true));
                                            String result = HexUtil.formatHexString(bluetoothGattCharacteristic.getValue(), true);
                                            String temp = "";

                                            for (int length = result.length(); length > 0; length--) {
                                                temp = temp + result.charAt(length - 1);
                                            }
                                            notify.setText("CO:" + temp + "ppm");
                                        }
                                    });
                                }
                            });

                } else {

                    BleDevice device = Utils.getDevice(mContext);
                    BluetoothGattService notifyService = Utils.getService(mContext, device, 4);
                    BluetoothGattCharacteristic bluetoothGattCharacteristic = Utils.getCharasterstic(notifyService, 2);
                    if (bluetoothGattCharacteristic==null|| notifyService ==null){
                        showToast("暂无设备连接");
                        return;
                    }
//                    BleDevice device = getDevice();
//                    BluetoothGattService notifyService = getService(device, 4);
//                    final BluetoothGattCharacteristic bluetoothGattCharacteristic = notifyService.getCharacteristics().get(2);

                    btnNotify.setText("notify(关)");
                    btnNotify.setTag("close");
                    BleManager.getInstance().stopNotify(
                            device,
                            bluetoothGattCharacteristic.getService().getUuid().toString(),
                            bluetoothGattCharacteristic.getUuid().toString());
                    notify.setText("notify: null");
                }

                break;
        }
    }

    private void setOnCharacteristicChanged(final TextView tvAcc, final byte[] data, final String acc) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                String result = HexUtil.formatHexString(data, true);
                String temp = "";

                for (int length = result.length(); length > 0; length--) {
                    temp = temp + result.charAt(length - 1);
                }

                tvAcc.setText("加速度："+":" + temp );
            }
        });
    }

    private String getCurrentStatus() {


        if (isCONotifyOpen) {
            status = "02";
        } else {
            status = "01";
        }
        isCONotifyOpen = !isCONotifyOpen;
        return status;
    }
}
